/*
Almaz-6 control unit
*/

#include "hardware.h"
#include "lcd.h"
#include "sys.h"
#include "keycodes.h"
#include "flags.h"
#include "utils.h"
#include "modes.h"
#include "menu.h"
#include "par.h"

#include <util/atomic.h>
#include <avr/interrupt.h>

/*** MAIN FUNCTION ***/

int main(void)
{

/* I/O ports setup */
PORTA = 0;
DDRA  = 0xFF;

PORTB = (0<<bo_LCD)|(1<<bo_KBD)|(0<<bo_RW)|(0<<bo_RS);
DDRB  = (1<<bo_LCD)|(1<<bo_KBD)|(1<<bo_RW)|(1<<bo_RS);

PORTC = 0;
DDRC  = 0xFF;

PORTD = dom_SEL;
DDRD  = dom_SEL;

PORTE = 0;
DDRE  = 0;

PORTF = 0xFF;
DDRF  = 0;

PORTG = 0;
DDRG  = 0xFF;

/* Timers setup */
/* Timer 0 - System timer 800 Hz */
TCCR0 = (1<<WGM01)|(0<<WGM00)|(1<<CS02)|(1<<CS01)|(0<<CS00); // 256 CTC-mode
OCR0 = 72;  // 14.7456MHz / 256 / 72 = 800Hz
/* Timer 2 - Motor timer */
TCCR2 = (1<<WGM21)|(0<<WGM20)|(0<<CS22)|(1<<CS21)|(1<<CS20); // 1024 CTC-mode
OCR2 = 72;
/* Timers interrupts enable */
TIMSK = (1<<OCIE0)|(1<<OCIE2);

/* MCU setup */
MCUCR = 0;
/* External interrupts setup */
EICRA = (1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00);
EICRB = 0;
EIMSK = (1<<INT1)|(1<<INT0);

InputInit();
VarInit();

sei ();

LCD_Init();

Splash();

(*Curr->Fun)(0);
Mode=_Stop_;

while(1)  // forever
  {
  if (!StepCounter) Flags &= ~F_Jump;//dirt hack
  //////////////0000000000000000000000000000000000000000000000 antimiss fag hack

 if((InpPattrn & IN_SP_DN1) && Mode==_Sawing_){
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
        Switch(OUT_SPDN|OUT_SPUP,OFF);
        Counter++;
        if(WCounter < Number)
          WCounter++;
        else
          Flags |= F_Finish;
        PAUSE(600);
        Switch(OUT_SPUP,ON);
        Mode=_SpindUp_;
        }
}
 if((InpPattrn & IN_SP_UP) && Mode==_SpindUp_){
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
    
    Switch(OUT_SPDN|OUT_SPUP,OFF);
    Pause(500); 
    if((Flags & F_Break) || (Flags & F_Finish))
      {
      if(Flags & F_Finish)
        {
        Switch(OUT_TBLF,OFF);
        Pause(600); 
        Switch(OUT_TBLB,ON);
        }
      Mode=_Stop_;
      }
    else
      {
      SetFeed();
      RUNMOTOR;
      Mode=_Feed_;
      }
     }
} 

//0000000000000000000000000000000000000000000000000000000000000
  cli ();
  if ((InpChange & IN_PWR) && (InpPattrn & IN_PWR)) {
  
        if (Flags & F_Power) {
    
            Switch (PWR_LATCH, OFF);
            Switch (OUT_BRAKE, OFF);
            Switch (OUT_COOLANT, OFF);
            InpChange = 0;
            cli ();
            Flags &= ~F_Power;
            Mode = _Stop_;
    
        } else {
        
            sei ();
            Switch (PWR_START, ON);
            PAUSE (330);
            Switch (PWR_LATCH, ON);
            PAUSE (30);
            Switch (PWR_START, OFF);
            Switch (OUT_BRAKE, ON);
            Switch (OUT_COOLANT, ON);
            cli ();
            Flags |= F_Power;
            Mode = _Stop_;
        };
    };
  
  if(!PauseCnt) 
    {
    if(Flags & F_PowerFail) 
      {
      Flags &= ~F_PowerFail;
      STOPMOTOR;
      Output(OutMsk);
      sei ();
      }
    else
      {
      sei ();
      //Switch (LED_SPUP,OFF);
      (*ModeArray[Mode])();
      }
    }
  sei ();
  
  if(Mode == _Stop_ || Mode == _Checkout_) KeyProcess();

  if(Curr->Idle) (*Curr->Idle)();
  
  }
  
}
